from aiohttp import ClientSession
from imbox import Imbox
from re import findall
from os.path import exists
from loguru import logger
import asyncio


providers = {
    "imap.rambler.ru": [
        'rambler.ru',
        'lenta.ru',
        'autorambler.ru',
        'myrambler.ru',
        'ro.ru',
        'rambler.ua'],
    "imap.mail.ru": ['mail.ru', 'internet.ru', 'bk.ru', 'inbox.ru', 'list.ru'],
    "imap.gmail.com": 'gmail.com',
    "imap.yandex.ru": 'yandex.ru',
}


def _get_email_provider(provider: str):
    pr = provider.split("@")[-1]

    for key, value in providers.items():
        if pr in value:
            return key

    return f"imap.{pr}"


def _get_imap(provider: str, login: str, password: str):
    return Imbox(
            provider,
            username=login,
            password=password,
            ssl=True,
            ssl_context=None,
            starttls=None)


async def recv_message(imbox: Imbox):
    folder = "Spam"
    for _, message in imbox.messages(folder=folder)[::-1]:
        if message.sent_from[0]["email"] == "hello@slingshot.finance":
            return findall(r"<a.*href=\"(.*?)\".*>VERIFY<\/a >",
                           message.body["plain"][0])[0]
    return await recv_message(imbox)


async def get_code_email(email: str, password: str):
    imbox = _get_imap(_get_email_provider(email), email, password)

    return await recv_message(imbox)


async def register_account(client: ClientSession, proxy: str, email: str, referrer: str):
    response = await client.post(
            "https://us-central1-slingshot-waitlist.cloudfunctions.net/signUp",
            json={
                "data": {
                    "email": email,
                    "referralCode": referrer
                }
            },
            proxy=proxy)

    data = await response.json()

    if "error" in data:
        raise Exception(data["error"]["message"])

    return True


async def verify_account(client: ClientSession, proxy: str, url: str, email: str):
    response = await client.get(
            url,
            proxy=proxy,
            allow_redirects=True)
    code = str(response.url).split("/")[-1]

    response = await client.post(
            "https://www.googleapis.com/identitytoolkit/v3/relyingparty/signupNewUser"
            "?key=AIzaSyAyHBgnYzpg9md9ysHkhekv1mYqq_zlFkE",
            json={
                'email': email,
                'password': code,
                'returnSecureToken': True,
            },
            proxy=proxy)

    data = await response.json()

    if "idToken" not in data:
        raise Exception("Хуета какая-то при реге я хуй знает че")

    client.headers.update({"Authorization": "Bearer " + data["idToken"]})

    response = await client.post(
                "https://us-central1-slingshot-waitlist.cloudfunctions.net/verifyEmail",
                json={
                    "data": {
                        "verificationCode": code
                    }
                },
                proxy=proxy)

    data = await response.json()

    if "result" not in data:
        raise Exception("Не удалось верифнуть почту")

    return True


async def worker(referrer: str, q: asyncio.Queue):
    while True:
        proxy, email = await q.get()

        email, password = email.split(":")

        try:
            async with ClientSession() as client:
                logger.info("Регистрация аккаунта")
                await register_account(client, proxy, email, referrer)

                logger.info("Получение кода с почты")
                code = await get_code_email(email, password)

                logger.info("Подтверждение кода")
                await verify_account(client, proxy, code, email)

                logger.info("Аккаунт успешно зарегистрирован")
        except Exception:
            logger.exception("Ошибка при реге")
        else:
            logger.info("Сохранение аккаунта")
            open("accounts.txt", "a+").write(f"{email}:{password}:{code}\n")


async def main():
    if not all([exists("proxy.txt"), exists("emails.txt")]):
        return logger.error("Не найдены файлы proxy.txt, emails.txt")

    proxy = open("proxy.txt", "r+").read().strip().split("\n")
    emails = open("emails.txt", "r+").read().strip().split("\n")
    referrer = input("реф код -> ")

    q = asyncio.Queue()

    for account in zip(proxy, emails):
        q.put_nowait(account)

    tasks = [asyncio.create_task(worker(referrer, q))
             for _ in range(int(input("Потоков -> ")))]

    await asyncio.gather(*tasks)


if __name__ == "__main__":
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)

    loop.run_until_complete(main())
